﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace Editor.Particles
{
    public abstract class BaseParticleSystem : DrawableGameComponent
    {
        public const int AlphaBlendDrawOrder = 100;
        public const int AdditiveDrawOrder = 200;

        private Editor.XNA.RenderWindow DisplayWindow;

        private Texture2D ParticleTexture;
        private Vector2 Origin;
        int NumberOfEffects;

        Particle[] ParticleSystem;
        Queue<Particle> FreeParticles;

        public int FreeParticleCount
        {
            get { return FreeParticles.Count; }
        }

        protected int MinimumNumberOfParticles;
        protected int MaximumNumberOfParticles;

        protected string TextureFileName;

        protected float MinimumInitialSpeed;
        protected float MaximumInitialSpeed;

        protected float MinimumAcceleration;
        protected float MaximumAcceleration;

        protected float MinimumRotationSpeed;
        protected float MaximumRotationSpeed;

        protected float MinimumLifetime;
        protected float MaximumLifetime;

        protected float MinimumScale;
        protected float MaximumScale;

        protected SpriteBlendMode spriteBlendMode;

        protected BaseParticleSystem(Editor.XNA.RenderWindow theRenderWindow, int EffectsCount) : base(
        {
            this.DisplayWindow = theRenderWindow;
            this.NumberOfEffects = EffectsCount;
        }

        public override void Initialize()
        {
            InitializeConstants();
            ParticleSystem = new Particle[NumberOfEffects * MaximumNumberOfParticles];
            FreeParticles = new Queue<Particle>(NumberOfEffects * MaximumNumberOfParticles);

            for (int i = 0; i < ParticleSystem.Length; i++)
            {
                ParticleSystem[i] = new Particle();
                FreeParticles.Enqueue(ParticleSystem[i]);
            }
            base.Initialize();
        }
        public abstract void InitializeConstants();
      

        protected override void LoadContent()
        {
            if (string.IsNullOrEmpty(TextureFileName))
            {
                ParticleTexture = DisplayWindow.content.Load<Texture2D>("NoTexture");
            }
            ParticleTexture = DisplayWindow.content.Load<Texture2D>(TextureFileName);
            Origin.X = ParticleTexture.Width / 2;
            Origin.Y = ParticleTexture.Height / 2;
            base.LoadContent();
        }

        public void AddParticles(Vector2 theLocation)
        {
            Random r = new Random();
            int numParticles = r.Next(MinimumNumberOfParticles, MaximumNumberOfParticles);

            for (int i = 0; i < numParticles && FreeParticles.Count > 0; i++)
            {
                Particle p = FreeParticles.Dequeue();
                InitializeParticle(p, theLocation);
            }
        }

        protected void InitializeParticle(Particle theParticle, Vector2 theLocation)
        {
            Random r = new Random();
            float theAngle = r.Next(0, (int)MathHelper.TwoPi);
            Vector2 theDirection = new Vector2((float)Math.Cos(theAngle), (float)Math.Sin(theAngle));
        }

        public override void Update(GameTime gameTime)
        {
            float dt = (float)gameTime.ElapsedGameTime.TotalSeconds;
            foreach (Particle p in ParticleSystem)
            {
                if (p.IsActive())
                {
                    p.Update(dt);
                    if (!p.IsActive())
                    {
                        FreeParticles.Enqueue(p);
                    }
                }
            }
            base.Update(gameTime);
        }

        public override void Draw(GameTime gameTime)
        {
            DisplayWindow.theBatch.Begin(spriteBlendMode);
            foreach (Particle p in ParticleSystem)
            {
                if (!p.IsActive())
                    continue;
                float normalizedLifetime = p.ParticleElapsedTime / p.Lifetime;
                float alpha = 4 * normalizedLifetime * (1 - normalizedLifetime);
                Color color = new Color(new Vector4(1,1,1,alpha));
                float scale = p.Scale * (0.75f + 0.25f * normalizedLifetime);
                DisplayWindow.theBatch.Draw(ParticleTexture, p.Position, null, color, p.Rotation, Origin, scale, SpriteEffects.None, 0.0f);
                
            }
            DisplayWindow.theBatch.End();
           base.Draw(gameTime);
        }
    }
}
